package com.zodiac.app.szse.parse;

import lombok.Getter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Getter
public class Cmd {

    private List<String> output = new ArrayList<>();
    private List<String> error = new ArrayList<>();
    private int exitValue;

    public static Cmd create() {
        return new Cmd();
    }

    /**
     * 执行命令
     *
     * @param command
     */
    public Cmd exec(String command) {
        try {
            exec(Runtime.getRuntime().exec(command));
            return this;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 执行命令
     *
     * @param cmdarray
     */
    public Cmd exec(String[] cmdarray) {
        try {
            exec(Runtime.getRuntime().exec(cmdarray));
            return this;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 命令处理
     *
     * @param process
     * @throws InterruptedException
     */
    private void exec(Process process) throws InterruptedException {
        new Thread(new NonBlocking(process, this, false)).start();
        new Thread(new NonBlocking(process, this, true)).start();
        this.exitValue = process.waitFor();
    }

    /**
     * 非阻塞
     */
    @Getter
    static class NonBlocking implements Runnable {
        private Process process;
        private Cmd cmd;
        private boolean errorStream;

        public NonBlocking(Process process, Cmd cmd, boolean errorStream) {
            this.process = process;
            this.cmd = cmd;
            this.errorStream = errorStream;
        }

        @Override
        public void run() {
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new InputStreamReader(this.isErrorStream() ? this.getProcess().getErrorStream() : this.getProcess().getInputStream()));
                final List<String> output = this.isErrorStream() ? this.getCmd().getError() : this.getCmd().getOutput();
                String line;
                while (null != (line = reader.readLine())) {
                    output.add(line);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                try {
                    if (Objects.nonNull(reader)) {
                        reader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
